package net.sk.china.city.talk.service.impl.system;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import net.sk.china.city.talk.constants.Constants;
import net.sk.china.city.talk.dao.system.SystemCityDao;
import net.sk.china.city.talk.model.system.SystemCity;
import net.sk.china.city.talk.request.system.SystemCitySearchRequest;
import net.sk.china.city.talk.response.system.SystemCityTreeResponse;
import net.sk.china.city.talk.service.system.SystemCityService;
import net.sk.china.common.utils.RedisUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * SystemCityServiceImpl 接口实现
 * +----------------------------------------------------------------------
 * // | Talk To [ 聊来改善地区金融服务环境，助力企业发展 ]
 * // +----------------------------------------------------------------------
 * // | Copyright (c) 2018-2024 聊来 All rights reserved.
 * // +----------------------------------------------------------------------
 * // | Licensed ( <a href="http://www.apache.org/licenses/LICENSE-2.0">apache</a> )
 * // +----------------------------------------------------------------------
 * // | @Author: 聊来 <18970881148@qq.com>
 * // +----------------------------------------------------------------------
 * // | DateTime: 2024/6/3 16:16
 * // +----------------------------------------------------------------------
 */
@Service
public class SystemCityServiceImpl extends ServiceImpl<SystemCityDao, SystemCity> implements SystemCityService {

    @Resource
    private SystemCityDao dao;

    private final RedisUtil redisUtil;

    public SystemCityServiceImpl(RedisUtil redisUtil) {
        this.redisUtil = redisUtil;
    }

    /**
     * 分页城市列表
     * @param request 搜索条件
     * @return {@code Object}
     */
    @Override
    public Object getList(SystemCitySearchRequest request) {
        Object list = redisUtil.hmGet(Constants.CITY_LIST, request.getParentId().toString());
        if (ObjectUtil.isNull(list)) {
            //城市数据，异步同步到redis，第一次拿不到数据，去数据库读取
            list = getCityList(request.getParentId());
        }
        return list;
    }

    /**
     * 修改状态
     * @param id 城市id
     * @param status 状态
     * @return {@code boolean}
     */
    @Override
    public boolean updateStatus(Integer id, Boolean status) {
        SystemCity systemCity = getById(id);
        systemCity.setId(id);
        systemCity.setIsShow(status);
        boolean result = updateById(systemCity);
        if (result) {
            asyncRedis(systemCity.getParentId());
        }
        return result;
    }

    /**
     * 修改城市
     * @param id 城市id
     * @param request 修改参数
     * @return {@code boolean}
     */
    @Override
    public Boolean update(Integer id, SystemCitySearchRequest request) {
        SystemCity systemCity = new SystemCity();
        BeanUtils.copyProperties(request, systemCity);
        systemCity.setId(id);
        boolean result = updateById(systemCity);
        if (result) {
            asyncRedis(request.getParentId());
        }
        return result;
    }

    /**
     * 获取城市树
     * @return {@code List<SystemCityTreeResponse>}
     */
    @Override
    public List<SystemCityTreeResponse> getListTree() {
        List<SystemCityTreeResponse> cityList = redisUtil.get(Constants.CITY_LIST_TREE);
        if (CollUtil.isEmpty(cityList)) { setListTree(); }
        return redisUtil.get(Constants.CITY_LIST_TREE);
    }

    /**
     * 获取所有城市cityId
     * @return {@code List<Integer>}
     */
    @Override
    public List<Integer> getCityIdList() {
        Object data = redisUtil.get(Constants.CITY_LIST_LEVEL_1);
        List<Integer> collect;
        String empty = "";
        if (data == null || data.equals(empty)) {
            LambdaQueryWrapper<SystemCity> query = new LambdaQueryWrapper<>();
            query.select(SystemCity::getCityId);
            query.eq(SystemCity::getLevel, 1);
            query.eq(SystemCity::getIsShow, true);
            List<SystemCity> systemCityList = dao.selectList(query);
            collect = systemCityList.stream().map(SystemCity::getCityId).distinct().collect(Collectors.toList());
            redisUtil.set(Constants.CITY_LIST_LEVEL_1, collect, 10L, TimeUnit.MINUTES);
        } else {
            collect = redisUtil.get(Constants.CITY_LIST_LEVEL_1);
        }

        return collect;
    }

    /**
     * 根据城市ID获取城市详细数据
     * @param cityId 城市id
     * @return {@code  SystemCity}
     */
    @Override
    public SystemCity getCityByCityId(Integer cityId) {
        LambdaQueryWrapper<SystemCity> query = new LambdaQueryWrapper<>();
        query.eq(SystemCity::getCityId, cityId);
        query.last("LIMIT 1");

        return getOne(query);
    }

    /**
     * 根据城市编码获取城市详细数据
     * @param areaCode 城市编码
     * @return {@code String}
     */
    @Override
    public String getCityByAreaCode(String areaCode) {
        if (StrUtil.isBlank(areaCode)) { return ""; }
        Object data = redisUtil.hmGet(Constants.CITY_CODE, areaCode);
        if (ObjectUtil.isNotNull(data)) {
            return (String) data;
        } else {
            LambdaQueryWrapper<SystemCity> query = new LambdaQueryWrapper<>();
            query.select(SystemCity::getName);
            query.eq(SystemCity::getAreaCode, areaCode);
            query.last("LIMIT 1");

            SystemCity systemCity = getOne(query);
            if (ObjectUtil.isNotNull(systemCity)) {
                redisUtil.hmSet(Constants.CITY_CODE, areaCode, systemCity.getName());
                return systemCity.getName();
            }

            return "";
        }

    }

    /**
     * 根据城市名称获取城市详细数据
     * @param cityName 城市名称
     * @return {@code SystemCity}
     */
    @Override
    public SystemCity getCityByCityName(String cityName) {
        LambdaQueryWrapper<SystemCity> query = Wrappers.lambdaQuery();
        query.eq(SystemCity::getName,cityName);
        query.last("LIMIT 1");

        return getOne(query);
    }

    /**
     * 根据父级id获取数据
     * @param parentId integer parentId
     * @return {@code Object}
     */
    private Object getCityList(Integer parentId) {
        LambdaQueryWrapper<SystemCity> query = new LambdaQueryWrapper<>();
        query.eq(SystemCity::getParentId, parentId);
        query.eq(SystemCity::getIsShow, true);
        query.orderByDesc(SystemCity::getSort).orderByDesc(SystemCity::getId);

        List<SystemCity> systemCityList = dao.selectList(query);
        if (systemCityList != null && systemCityList.size() > 0) {
            redisUtil.hmSet(Constants.CITY_LIST, parentId.toString(), systemCityList);
            setListTree();
        }


        return systemCityList;
    }

    /**
     * 数据整体刷入redis
     */
    private void asyncRedis(Integer pid) {
        LambdaQueryWrapper<SystemCity> query = new LambdaQueryWrapper<>();
        query.eq(SystemCity::getParentId, pid);
        query.eq(SystemCity::getIsShow, true);
        List<SystemCity> systemCityList = dao.selectList(query);
        if (systemCityList != null && systemCityList.size() > 0) {
            redisUtil.hmSet(Constants.CITY_LIST, pid.toString(), systemCityList);
        }
        setListTree();
    }

    /**
     * 设置属性列表进入redis
     */
    private void setListTree() {
        // 循环数据，把数据对象变成带list结构的vo
        List<SystemCityTreeResponse> treeList = new ArrayList<>();

        LambdaQueryWrapper<SystemCity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(SystemCity::getId, SystemCity::getCityId, SystemCity::getParentId, SystemCity::getName);
        lambdaQueryWrapper.eq(SystemCity::getIsShow, true);
        List<SystemCity> allTree = dao.selectList(lambdaQueryWrapper);
        if (CollUtil.isEmpty(allTree)) {
            return;
        }

        for (SystemCity systemCity : allTree) {
            SystemCityTreeResponse systemCityTreeVo = new SystemCityTreeResponse();
            BeanUtils.copyProperties(systemCity, systemCityTreeVo);
            treeList.add(systemCityTreeVo);
        }
        // 返回
        Map<Integer, SystemCityTreeResponse> map = new HashMap<>(16);
        // cityId 为 key 存储到map 中
        for (SystemCityTreeResponse item : treeList) {
            map.put(item.getCityId(), item);
        }
        List<SystemCityTreeResponse> list = new ArrayList<>();
        for (SystemCityTreeResponse tree : treeList) {
            //子集ID返回对象，有则添加。
            SystemCityTreeResponse tree1 = map.get(tree.getParentId());
            if (tree1 != null) {
                tree1.getChild().add(tree);
            } else {
                list.add(tree);
            }
        }
        redisUtil.set(Constants.CITY_LIST_TREE, list);
    }
}
